package com.to8to.kitt.esb.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map.Entry;

import org.apache.thrift.TApplicationException;
import org.apache.thrift.TServiceClient;

import com.to8to.kitt.utils.LogUtils;


public class ThriftClientInvocationHandler implements InvocationHandler {
	
	private String service;
	
	public ThriftClientInvocationHandler(String service) {
		this.service = service;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		Entry<String, TServiceClient> entry = ThriftClientPoolFactory.getThreadLocalClient(service);
		LogUtils.logger().debug("开始访问。。。ESB实例:{}, 线程id:{}, 服务名:{}, 方法名:{}, 请求参数:{}"
				, entry.getKey(), Thread.currentThread().getId(), service, method, args);
		try {	
			result = method.invoke(entry.getValue(), args);
		} catch (Exception e) {
			LogUtils.logger().error("访问失败!!! ESB实例异常!!! ESB实例:{}, 线程id:{}, 服务名:{}, 方法名:{}, 请求参数:{}\n Exception:{}\n cause:{} \n cause.cause:{}"
					, entry.getKey(), Thread.currentThread().getId(), service, method, args
					, e, e.getCause(), (e.getCause() != null ? e.getCause().getCause():""));
			caughtThrowable(service, entry.getKey(), e);
		}
		LogUtils.logger().debug("访问成功 ... ESB实例:{}, 线程id:{}, 服务名:{}, 返回值:{}", entry.getKey(), Thread.currentThread().getId(), service, result);
		return result;
	}
	
	public void caughtThrowable(String service, String instance, Exception e) {
		
		Throwable cause = e.getCause();
		
		boolean reconnect = true;
		
		if (cause != null) 
		{	
			if(cause instanceof TApplicationException) //服务器内部异常
			{
				LogUtils.logger().error("服务器内部抛出异常: TApplicationException!!! \n{}", cause);
				reconnect = false;
			}
		}
		
		if(reconnect)
		{
			long id = Thread.currentThread().getId();
			ThriftClientPool pool = ThriftClientPoolFactory.ClientMap.get(service + "_" + id);
			if(pool != null)
			{
				LogUtils.logger().error("ESB实例连接有问题，强制下线:{}, 异常信息:{}", instance, e.toString() + "\n" + e.getCause().toString());
				pool.remove(instance);
			}
		}
	}

}